Neste projeto, você usará redes adversárias geradoras para gerar novas imagens de faces.
Você estará usando dois conjuntos de dados neste projeto:
Como o conjunto de dados celebA é complexo e você está fazendo GANs em um projeto pela primeira vez, queremos que você teste sua rede neural no MNIST antes da CelebA. Executar as GANs no MNIST permitirá que você veja o quão bem seu modelo treina mais cedo.
Se você estiver usando o [FloydHub] (https://www.floydhub.com/), defina data_dir como" / input "e use o [FloydHub data ID] (http://docs.floydhub.com/home / using_datasets /) "R5KrjnANiKVhLWAkpXhNBe".
data_dir = './data'
import helper
helper.download_extract('mnist', data_dir)
helper.download_extract('celeba', data_dir)
Como você sabe, o conjunto de dados [MNIST] (http://yann.lecun.com/exdb/mnist/) contém imagens de dígitos manuscritos. Você pode ver o primeiro número de exemplos mudando show_n_images.
show_n_images = 25
%matplotlib inline
import os
from glob import glob
from matplotlib import pyplot
mnist_images = helper.get_batch(glob(os.path.join(data_dir, 'mnist/*.jpg'))[:show_n_images], 28, 28, 'L')
pyplot.imshow(helper.images_square_grid(mnist_images, 'L'), cmap='gray')
O conjunto de dados [CelebA Attributes Dataset (CelebA)] (http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html) contém mais de 200.000 imagens de celebridades com anotações. Como você vai gerar faces, não precisará das anotações. Você pode ver o primeiro número de exemplos mudando show_n_images.
show_n_images = 25
mnist_images = helper.get_batch(glob(os.path.join(data_dir, 'img_align_celeba/*.jpg'))[:show_n_images], 28, 28, 'RGB')
pyplot.imshow(helper.images_square_grid(mnist_images, 'RGB'))
Como o foco principal do projeto é construir as GANs, nós pré-processaremos os dados para você. Os valores do conjunto de dados MNIST e CelebA estarão no intervalo de -0,5 a 0,5 de 28x28 imagens dimensionais. As imagens da CelebA serão cortadas para remover partes da imagem que não incluem um rosto e redimensionadas para 28x28.
As imagens MNIST são imagens em preto e branco com um único [canal de cor] (https://en.wikipedia.org/wiki/Channel_ (digitalimage% 29), enquanto as imagens da CelebA têm [3 canais de cores (canal de cores RGB)] ( https://en.wikipedia.org/wiki/Channel(digital_image%29#RGB_Images).
Você construirá os componentes necessários para construir uma GAN implementando as seguintes funções abaixo:
model_inputsdiscriminadorgeradormodel_lossmodel_opttrainIsso irá verificar se você tem a versão correta do TensorFlow e acesso a uma GPU
from distutils.version import LooseVersion
import warnings
import tensorflow as tf
# Verificar versão do Tensorflow
assert LooseVersion(tf.__version__) >= LooseVersion('1.0'), 'Please use TensorFlow version 1.0 or newer. You are using {}'.format(tf.__version__)
print('TensorFlow Version: {}'.format(tf.__version__))
# Checar GPU
if not tf.test.gpu_device_name():
warnings.warn('GPU Não encontrada. Por favor utilize uma GPU para treinar sua rede neural.')
else:
print('GPU: {}'.format(tf.test.gpu_device_name()))
Implemente a função model_inputs para criar espaços reservados para TF para a rede neural. Deve criar os seguintes marcadores de posição:
image_width,image_height e image_channels.z_dim.Retorna os marcadores de posição a seguir da tupla (tensor de imagens de entrada reais, tensor de dados z)
import problem_unittests as tests
def model_inputs(image_width, image_height, image_channels, z_dim):
input_feat = tf.placeholder(dtype=tf.float32, shape=(None, image_width, image_height, image_channels),
name='r_input')
input_dim = tf.placeholder(dtype=tf.float32,shape=(None, z_dim), name='z_input')
learning_rate = tf.placeholder(dtype=tf.float32, name='lr')
return input_feat, input_dim, learning_rate
tests.test_model_inputs(model_inputs)
Implemente discriminator para criar uma rede neural discriminadora que discrimineimages. Esta função deve ser capaz de reutilizar as variáveis na rede neural. Use [tf.variable_scope] (https://www.tensorflow.org/api_docs/python/tf/variable_scope) com um nome de escopo de" discriminador "para permitir que as variáveis sejam reutilizadas. A função deve retornar uma tupla de (tensor output do discriminador, tensor logits do discriminador).
def discriminator(images, reuse=False):
with tf.variable_scope('discriminator', reuse=reuse):
alpha = 0.2
dropout=0.9
hl1 = tf.layers.conv2d(images, 64, 5, strides=2, padding='same')
hl1 = tf.maximum(alpha * hl1, hl1)
hl2 = tf.layers.conv2d(hl1, 128, 5, strides=2, padding='same')
hl2 = tf.layers.batch_normalization(hl2, training=True)
hl2 = tf.maximum(alpha * hl2, hl2)
hl3 = tf.layers.conv2d(hl2, 256, 5, strides=2, padding='same')
hl3 = tf.layers.batch_normalization(hl3, training=True)
hl3 = tf.maximum(alpha * hl3, hl3)
inp_f = tf.reshape(hl3, (-1, 4*4*256))
dl = tf.layers.dropout(inputs=inp_f, rate=dropout)
logits = tf.layers.dense(dl, 1)
output = tf.sigmoid(logits)
return output, logits
tests.test_discriminator(discriminator, tf)
Implemente generator para gerar uma imagem usandoz. Esta função deve ser capaz de reutilizar as variáveis na rede neural. Use [tf.variable_scope] (https://www.tensorflow.org/api_docs/python/tf/variable_scope) com um nome de escopo de" generator "para permitir que as variáveis sejam reutilizadas. A função deve retornar as imagens 28 x 28 x out_channel_dim geradas.
def generator(z, out_channel_dim, is_train=True):
with tf.variable_scope('generator', reuse= not is_train):
alpha = 0.2
dropout=0.9
hl1 = tf.layers.dense(z, 3*3*512) # Dimensões
hl1 = tf.reshape(hl1, (-1, 3, 3, 512)) # Novo shape
hl1 = tf.layers.batch_normalization(hl1, training=is_train)
hl1 = tf.maximum(alpha * hl1, hl1)
hl2 = tf.layers.conv2d_transpose(hl1, 256, kernel_size=4, strides=2, padding='same')
hl2 = tf.layers.batch_normalization(hl2, training=is_train)
hl2 = tf.maximum(alpha * hl2, hl2)
hl3 = tf.layers.conv2d_transpose(hl2, 128, kernel_size=4, strides=2, padding='valid')
hl3 = tf.layers.batch_normalization(hl3, training=is_train)
hl3 = tf.maximum(alpha * hl3, hl3)
logits = tf.layers.conv2d_transpose(hl3, out_channel_dim, kernel_size=5,strides=2, padding='same')
output = tf.tanh(logits)
return output
tests.test_generator(generator, tf)
Implemente model_loss para construir as GANs para treinamento e calcular a perda. A função deve retornar uma tupla de (perda do discriminador, perda do gerador). Use as seguintes funções que você implementou:
discriminador (imagens, reutilização = Falso)gerador (z, out_channel_dim, is_train = True)def model_loss(input_real, input_z, out_channel_dim):
smooth=0.1
generatorr = generator(input_z, out_channel_dim, is_train=True)
discriminatorr, r_logits = discriminator(input_real, reuse=False)
f_model, f_logits = discriminator(generatorr, reuse=True)
r_loss = tf.reduce_mean(
tf.nn.sigmoid_cross_entropy_with_logits(logits=r_logits,
labels=tf.ones_like(discriminatorr)*(1 - smooth)))
f_loss = tf.reduce_mean(
tf.nn.sigmoid_cross_entropy_with_logits(logits=f_logits, labels=tf.zeros_like(f_model)))
g_loss = tf.reduce_mean(
tf.nn.sigmoid_cross_entropy_with_logits(logits=f_logits, labels=tf.ones_like(f_model)))
d_loss = r_loss + f_loss
return d_loss, g_loss
return None, None
tests.test_model_loss(model_loss)
Implemente model_opt para criar as operações de otimização para as GANs. Use [tf.trainable_variables] (https://www.tensorflow.org/api_docs/python/tf/trainable_variables) para obter todas as variáveis treináveis. Filtre as variáveis com nomes que estão nos nomes do escopo do discriminador e do gerador. A função deve retornar uma tupla de (operação de treinamento do discriminador, operação de treinamento do gerador).
def model_opt(d_loss, g_loss, learning_rate, beta1):
train_var = tf.trainable_variables()
discriminator_var = [var for var in train_var if var.name.startswith('discriminator')]
generator_var = [var for var in train_var if var.name.startswith('generator')]
# Otimizzando...
with tf.control_dependencies(tf.get_collection(tf.GraphKeys.UPDATE_OPS)):
dis_train_opt = tf.train.AdamOptimizer(learning_rate, beta1=beta1).minimize(d_loss, var_list=discriminator_var)
gen_train_opt = tf.train.AdamOptimizer(learning_rate, beta1=beta1).minimize(g_loss, var_list=generator_var)
return dis_train_opt, gen_train_opt
tests.test_model_opt(model_opt, tf)
import numpy as np
def show_generator_output(sess, n_images, input_z, out_channel_dim, image_mode):
cmap = None if image_mode == 'RGB' else 'gray'
z_dim = input_z.get_shape().as_list()[-1]
example_z = np.random.uniform(-1, 1, size=[n_images, z_dim])
samples = sess.run(
generator(input_z, out_channel_dim, False),
feed_dict={input_z: example_z})
images_grid = helper.images_square_grid(samples, image_mode)
pyplot.imshow(images_grid, cmap=cmap)
pyplot.show()
Implementar o train para construir e treinar as GANs. Use as seguintes funções que você implementou:
model_inputs (image_width, image_height, image_channels, z_dim)model_loss (input_real, input_z, out_channel_dim)model_opt (d_loss, g_loss, learning_rate, beta1)Use o show_generator_output para mostrar a saída dogenerator enquanto você treina. Executar show_generator_output para cada lote aumentará drasticamente o tempo de treinamento e aumentará o tamanho do bloco de anotações. É recomendado imprimir a saída do gerador a cada 100 lotes.
def train(epoch_count, batch_size, z_dim, learning_rate, beta1, get_batches, data_shape, data_image_mode):
print_step = 10
show_step = 100
leaky_alpha = 0.2
dropout = 0.75
images_to_show = 9
losses =[]
step = 0
_, width, height, channels = data_shape
r_input, z_input, lr = model_inputs(width, height, channels, z_dim)
d_loss, g_loss = model_loss(r_input, z_input, channels)
d_opt, g_opt = model_opt(d_loss, g_loss, lr, beta1)
print("Starting trainning")
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for epoch_i in range(epoch_count):
for batch_images in get_batches(batch_size):
step += 1
batch_images = 2*batch_images
# Random Noise as input
z_batch = np.random.uniform(-1, 1, size=(batch_size, z_dim))
_ = sess.run(d_opt, feed_dict={r_input: batch_images, z_input: z_batch, lr: learning_rate})
# Let the generator run twice, so that the discriminator does not converge that fast.
_ = sess.run(g_opt, feed_dict={z_input: z_batch, r_input: batch_images, lr: learning_rate})
if step % print_step == 0:
train_loss_d = d_loss.eval({z_input: z_batch, r_input: batch_images})
train_loss_g = g_loss.eval({z_input: z_batch})
print("Step: {}:".format(step),
"Epoch {}/{}...".format(epoch_i+1, epoch_count),
"Discriminator Loss: {:.4f}...".format(train_loss_d),
"Generator Loss: {:.4f}".format(train_loss_g))
losses.append((train_loss_d, train_loss_g))
if step % show_step == 0:
show_generator_output(sess, images_to_show, z_input, channels, data_image_mode)
print("Finished with trainning")
Teste sua arquitetura de GANs no MNIST. Depois de 2 épocas, as GANs devem poder gerar imagens que se pareçam com dígitos manuscritos. Certifique-se de que a perda do gerador seja menor que a perda do discriminador ou próxima de 0.
batch_size = 32
z_dim = 200
learning_rate = 0.0002
beta1 = 0.3
epochs = 2
mnist_dataset = helper.Dataset('mnist', glob(os.path.join(data_dir, 'mnist/*.jpg')))
with tf.Graph().as_default():
train(epochs, batch_size, z_dim, learning_rate, beta1, mnist_dataset.get_batches,
mnist_dataset.shape, mnist_dataset.image_mode)
Execute suas GANs na CelebA. Demora cerca de 20 minutos na GPU média para executar uma época. Você pode executar toda a época ou parar quando começar a gerar faces realistas.
batch_size = 32
z_dim = 200
learning_rate = 0.0002
beta1 = 0.3
epochs = 1
celeba_dataset = helper.Dataset('celeba', glob(os.path.join(data_dir, 'img_align_celeba/*.jpg')))
with tf.Graph().as_default():
train(epochs, batch_size, z_dim, learning_rate, beta1, celeba_dataset.get_batches,
celeba_dataset.shape, celeba_dataset.image_mode)
Ao enviar este projeto, certifique-se de executar todas as células antes de salvar o bloco de anotações. Salve o arquivo do notebook como "dlnd_face_generation.ipynb" e salve-o como um arquivo HTML em "File" -> "Download as". Inclua os arquivos "helper.py" e "problem_unittests.py" no seu envio.